/*  This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or (at
    your option) any later version.
    For more details, see the GNU Lesser General Public License (www.fsf.org
    or the COPYING file somewhere in the package)
 */

#include "ServiceRegistry.hh"

/*! @file src/OSGi/ServiceRegistry.cc
    @brief Class OSGi::ServiceRegistry (non-inline) methods.
    @author @ref Guillaume_Terrissol
    @date 27th December 2009 - 22nd January 2014
    @note This file is distributed under the LGPL license.
    Refer to the file COPYING (or http://www.fsf.org) for more information.
 */

#include "Exception.hh"

namespace OSGi
{
//------------------------------------------------------------------------------
//                           Constructor & Destructor
//------------------------------------------------------------------------------

    /*! Defaulted.
     */
    ServiceRegistry::ServiceRegistry() = default;


    /*! @note Checks out every service still registered
     */
    ServiceRegistry::~ServiceRegistry()
    {
        while(!mServices.empty())
        {
            checkOut(begin(mServices)->first);
        }
    }


//------------------------------------------------------------------------------
//                     Service Registry : Service Management
//------------------------------------------------------------------------------

    /*! @param pName    Name of the service to register
        @param pService Service to register
        @signal serviceRegistered()
     */
    void ServiceRegistry::checkIn(std::string pName, Service::Ptr pService)
    {
        if (mServices.find(pName) == end(mServices))
        {
            mServices[pName] = pService;
            OSGI_EMIT serviceRegistered(pService);
        }
        else
        {
            throw LogicError{"Already existing service : " + pName};
        }
    }


    /*! @param pName Name of the [previously checked in] service to unregister
        @signal serviceUnregistered()
     */
    void ServiceRegistry::checkOut(const std::string& pName)
    {
        auto    lIter = mServices.find(pName);
        if (lIter != end(mServices))
        {
            Service::Ptr    lService = lIter->second;
            mServices.erase(lIter);
            OSGI_EMIT serviceUnregistered(lService);
        }
    }


    /*! @param pService [previously checked in] Service to unregister
        @signal serviceUnregistered()
     */
    void ServiceRegistry::checkOut(Service::Ptr pService)
    {
        for(auto lIter = begin(mServices); lIter != end(mServices); ++lIter)
        {
            if (lIter->second == pService)
            {
                mServices.erase(lIter);
                OSGI_EMIT serviceUnregistered(pService);
                break;
            }
        }
    }


    /*! @param pName Name of the service to find
        @return The service named @p pName, if defined, a null pointer otherwise
     */
    Service::Ptr ServiceRegistry::findByName(const std::string& pName)
    {
        auto    lService = mServices.find(pName);
        if (lService != end(mServices))
        {
            return lService->second;
        }
        else
        {
            return {};
        }
    }
}
